home *** CD-ROM | disk | FTP | other *** search
/ User's Choice Windows CD / User's Choice Windows CD (CMS Software)(1993).iso / win_u_z / xlock_dv.zip / SOURCES.ZIP / LIFE.C < prev    next >
C/C++ Source or Header  |  1992-09-02  |  12KB  |  537 lines

  1. #ifndef lint
  2. static char sccsid[] = "@(#)life.c 22.1 89/09/20";
  3. #endif
  4. /*-
  5.  * life.c - Conway's game of Life for the xlock X11 terminal locker.
  6.  *
  7.  * Copyright (c) 1989 by Sun Microsystems, Inc.
  8.  *
  9.  * Permission to use, copy, modify, and distribute this software and its
  10.  * documentation for any purpose and without fee is hereby granted,
  11.  * provided that the above copyright notice appear in all copies and that
  12.  * both that copyright notice and this permission notice appear in
  13.  * supporting documentation.
  14.  *
  15.  * This file is provided AS IS with no warranties of any kind.    The author
  16.  * shall have no liability with respect to the infringement of copyrights,
  17.  * trade secrets or any patents by this file or any part thereof.  In no
  18.  * event will the author be liable for any lost revenue or profits or
  19.  * other special, indirect and consequential damages.
  20.  *
  21.  * Comments and additions should be sent to the authors:
  22.  *
  23.  *               flar@sun.com or naughton@sun.com
  24.  *
  25.  *               James A. Graham
  26.  *               Patrick J. Naughton
  27.  *               Window Systems Group, MS 14-40
  28.  *               Sun Microsystems, Inc.
  29.  *               2550 Garcia Ave
  30.  *               Mountain View, CA  94043
  31.  *
  32.  * Revision History:
  33.  * 20-Sep-89: Written.
  34.  */
  35.  
  36. #include <X11/Xos.h>
  37. #include <X11/Xlib.h>
  38. #include <X11/Xutil.h>
  39. #include "lifeicon.bit"
  40.  
  41. static XImage logo = {
  42.     0, 0,            /* width, height */
  43.     0, XYBitmap, 0,        /* xoffset, format, data */
  44.     LSBFirst, 8,        /* byte-order, bitmap-unit */
  45.     LSBFirst, 8, 1        /* bitmap-bit-order, bitmap-pad, depth */
  46. };
  47.  
  48. static Display *Dsp;
  49. static Window Win;
  50. static GC   Gc;
  51. static GC   eraseGC = (GC) 0;
  52. static int  timeout;
  53. static int  shooter;
  54. static int  delay;
  55. static int  color;
  56. static int  pixels;
  57. static int  width,
  58.             height;
  59. static int  xs,
  60.             ys,
  61.             xb,
  62.             yb;
  63. static long startTime;
  64.  
  65. #define    NROWS    32
  66. #define NCOLS    32
  67.  
  68. /* Buffer stores the data for each cell.  Each cell is stored as
  69.  * 8 bits representing the presence of a critter in each of it's
  70.  * surrounding 8 cells.     There is an empty row and column around
  71.  * the whole array to allow stores without bounds checking as well
  72.  * as an extra row at the end for the fetches into tempbuf.
  73.  */
  74. #define    UPLT    0x01
  75. #define UP    0x02
  76. #define UPRT    0x04
  77. #define LT    0x08
  78. #define RT    0x10
  79. #define DNLT    0x20
  80. #define DN    0x40
  81. #define DNRT    0x80
  82. static unsigned char buffer[(NROWS + 2) * (NCOLS + 2) + 2];
  83. static unsigned char agebuf[(NROWS + 2) * (NCOLS + 2)];
  84.  
  85. /* Tempbuf stores the data for the next two rows so that we know
  86.  * the state of those critter before he was modified by the fate
  87.  * of the critters that have already been processed.
  88.  */
  89. static unsigned char tempbuf[NCOLS * 2];
  90.  
  91. /* Fates is a lookup table for the fate of a critter.  The 256
  92.  * entries represent the 256 possible combinations of the 8
  93.  * neighbor cells.  Each entry is one of BIRTH (create a cell
  94.  * or leave one alive), SAME (leave the cell alive or dead),
  95.  * or DEATH (kill anything in the cell).
  96.  */
  97. #define BIRTH    0
  98. #define SAME    1
  99. #define DEATH    2
  100. static unsigned char fates[256];
  101.  
  102.  
  103. static int  patterns[][200] = {
  104.     {                /* EIGHT */
  105.     -3, -3, -2, -3, -1, -3,
  106.     -3, -2, -2, -2, -1, -2,
  107.     -3, -1, -2, -1, -1, -1,
  108.     0, 0, 1, 0, 2, 0,
  109.     0, 1, 1, 1, 2, 1,
  110.     0, 2, 1, 2, 2, 2,
  111.     99
  112.     },
  113.     {                /* PULSAR */
  114.     1, 1, 2, 1, 3, 1, 4, 1, 5, 1,
  115.     1, 2, 5, 2,
  116.     99
  117.     },
  118.     {                /* BARBER */
  119.     -7, -7, -6, -7,
  120.     -7, -6, -5, -6,
  121.     -5, -4, -3, -4,
  122.     -3, -2, -1, -2,
  123.     -1, 0, 1, 0,
  124.     1, 2, 3, 2,
  125.     3, 4, 5, 4,
  126.     4, 5, 5, 5,
  127.     99
  128.     },
  129.     {                /* HERTZ */
  130.     -2, -6, -1, -6,
  131.     -2, -5, -1, -5,
  132.     -7, -3, -6, -3, -2, -3, -1, -3, 0, -3, 1, -3, 5, -3, 6, -3,
  133.     -7, -2, -5, -2, -3, -2, 2, -2, 4, -2, 6, -2,
  134.     -5, -1, -3, -1, -2, -1, 2, -1, 4, -1,
  135.     -7, 0, -5, 0, -3, 0, 2, 0, 4, 0, 6, 0,
  136.     -7, 1, -6, 1, -2, 1, -1, 1, 0, 1, 1, 1, 5, 1, 6, 1,
  137.     -2, 3, -1, 3,
  138.     -2, 4, -1, 4,
  139.     99
  140.     },
  141.     {                /* TUMBLER */
  142.     -6, -6, -5, -6, 6, -6, 7, -6,
  143.     -6, -5, -5, -5, 6, -5, 7, -5,
  144.     -5, 5, 6, 5,
  145.     -7, 6, -5, 6, 6, 6, 8, 6,
  146.     -7, 7, -5, 7, 6, 7, 8, 7,
  147.     -7, 8, -6, 8, 7, 8, 8, 8,
  148.     99
  149.     },
  150.     {                /* PERIOD4 */
  151.     -5, -8, -4, -8,
  152.     -7, -7, -5, -7,
  153.     -8, -6, -2, -6,
  154.     -7, -5, -3, -5, -2, -5,
  155.     -5, -3, -3, -3,
  156.     -4, -2,
  157.     99
  158.     },
  159.     {                /* PERIOD5 */
  160.     -5, -8, -4, -8,
  161.     -6, -7, -3, -7,
  162.     -7, -6, -2, -6,
  163.     -8, -5, -1, -5,
  164.     -8, -4, -1, -4,
  165.     -7, -3, -2, -3,
  166.     -6, -2, -3, -2,
  167.     -5, -1, -4, -1,
  168.     99
  169.     },
  170.     {                /* PERIOD6 */
  171.     -4, -8, -3, -8,
  172.     -8, -7, -7, -7, -5, -7,
  173.     -8, -6, -7, -6, -4, -6, -1, -6,
  174.     -3, -5, -1, -5,
  175.     -2, -4,
  176.     -3, -2, -2, -2,
  177.     -3, -1, -2, -1,
  178.     99
  179.     },
  180.     {                /* PINWHEEL */
  181.     -4, -8, -3, -8,
  182.     -4, -7, -3, -7,
  183.     -4, -5, -3, -5, -2, -5, -1, -5,
  184.     -5, -4, -3, -4, 0, -4, 2, -4, 3, -4,
  185.     -5, -3, -1, -3, 0, -3, 2, -3, 3, -3,
  186.     -8, -2, -7, -2, -5, -2, -2, -2, 0, -2,
  187.     -8, -1, -7, -1, -5, -1, 0, -1,
  188.     -4, 0, -3, 0, -2, 0, -1, 0,
  189.     -2, 2, -1, 2,
  190.     -2, 3, -1, 3,
  191.     99
  192.     },
  193.     {                /* ] */
  194.     -1, -1, 0, -1, 1, -1,
  195.     0, 0, 1, 0,
  196.     -1, 1, 0, 1, 1, 1,
  197.     99
  198.     },
  199.     {                /* cc: */
  200.     -3, -1, -2, -1, -1, -1, 1, -1, 2, -1, 3, -1,
  201.     -3, 0, -2, 0, 1, 0, 2, 0,
  202.     -3, 1, -2, 1, -1, 1, 1, 1, 2, 1, 3, 1,
  203.     99
  204.     },
  205.     {                /* DOLBY */
  206.     -3, -1, -2, -1, -1, -1, 1, -1, 2, -1, 3, -1,
  207.     -3, 0, -2, 0, 2, 0, 3, 0,
  208.     -3, 1, -2, 1, -1, 1, 1, 1, 2, 1, 3, 1,
  209.     99
  210.     },
  211.     {                /* HORIZON */
  212.     -15, 0, -14, 0, -13, 0, -12, 0, -11, 0,
  213.     -10, 0, -9, 0, -8, 0, -7, 0, -6, 0,
  214.     -5, 0, -4, 0, -3, 0, -2, 0, -1, 0,
  215.     4, 0, 3, 0, 2, 0, 1, 0, 0, 0,
  216.     9, 0, 8, 0, 7, 0, 6, 0, 5, 0,
  217.     14, 0, 13, 0, 12, 0, 11, 0, 10, 0,
  218.     99
  219.     },
  220.     {                /* SHEAR */
  221.     -7, -2, -6, -2, -5, -2, -4, -2, -3, -2,
  222.     -2, -2, -1, -2, 0, -2, 1, -2, 2, -2,
  223.     -5, -1, -4, -1, -3, -1, -2, -1, -1, -1,
  224.     0, -1, 1, -1, 2, -1, 3, -1, 4, -1,
  225.     -3, 0, -2, 0, -1, 0, 0, 0, 1, 0,
  226.     2, 0, 3, 0, 4, 0, 5, 0, 6, 0,
  227.     -10, 1, -9, 1, -8, 1, -7, 1, -6, 1,
  228.     -5, 1, -4, 1, -3, 1, -2, 1, -1, 1,
  229.     -10, 2, -9, 2, -8, 2, -7, 2, -6, 2,
  230.     -5, 2, -4, 2, -3, 2, -2, 2, -1, 2,
  231.     99
  232.     },
  233.     {                /* VERTIGO */
  234.     0, -7,
  235.     0, -6,
  236.     0, -5,
  237.     0, -4,
  238.     0, -3,
  239.     0, -2,
  240.     0, -1,
  241.     0, 0,
  242.     0, 7,
  243.     0, 6,
  244.     0, 5,
  245.     0, 4,
  246.     0, 3,
  247.     0, 2,
  248.     0, 1,
  249.     99
  250.     },
  251.     {                /* CROSSBAR */
  252.     -5, 0, -4, 0, -3, 0, -2, 0, -1, 0, 4, 0, 3, 0, 2, 0, 1, 0, 0, 0,
  253.     99
  254.     },
  255.     {                /* GOALPOSTS */
  256.     -8, -7, 8, -7,
  257.     -8, -6, 8, -6,
  258.     -8, -5, 8, -5,
  259.     -8, -4, 8, -4,
  260.     -8, -3, 8, -3,
  261.     -8, -2, 8, -2,
  262.     -8, -1, 8, -1,
  263.     -8, 0, 8, 0,
  264.     -8, 1, 8, 1,
  265.     -8, 2, 8, 2,
  266.     -8, 3, 8, 3,
  267.     -8, 4, 8, 4,
  268.     -8, 5, 8, 5,
  269.     -8, 6, 8, 6,
  270.     -8, 7, 8, 7,
  271.     99
  272.     },
  273.     {                /* \ */
  274.     -8, -8, -7, -8,
  275.     -7, -7, -6, -7,
  276.     -6, -6, -5, -6,
  277.     -5, -5, -4, -5,
  278.     -4, -4, -3, -4,
  279.     -3, -3, -2, -3,
  280.     -2, -2, -1, -2,
  281.     -1, -1, 0, -1,
  282.     0, 0, 1, 0,
  283.     1, 1, 2, 1,
  284.     2, 2, 3, 2,
  285.     3, 3, 4, 3,
  286.     4, 4, 5, 4,
  287.     5, 5, 6, 5,
  288.     6, 6, 7, 6,
  289.     7, 7, 8, 7,
  290.     99
  291.     },
  292.     {                /* LABYRINTH */
  293.     -4, -4, -3, -4, -2, -4, -1, -4, 0, -4, 1, -4, 2, -4, 3, -4, 4, -4,
  294.     -4, -3, 0, -3, 4, -3,
  295.     -4, -2, -2, -2, -1, -2, 0, -2, 1, -2, 2, -2, 4, -2,
  296.     -4, -1, -2, -1, 2, -1, 4, -1,
  297.     -4, 0, -2, 0, -1, 0, 0, 0, 1, 0, 2, 0, 4, 0,
  298.     -4, 1, -2, 1, 2, 1, 4, 1,
  299.     -4, 2, -2, 2, -1, 2, 0, 2, 1, 2, 2, 2, 4, 2,
  300.     -4, 3, 0, 3, 4, 3,
  301.     -4, 4, -3, 4, -2, 4, -1, 4, 0, 4, 1, 4, 2, 4, 3, 4, 4, 4,
  302.     99
  303.     }
  304. };
  305.  
  306. #define NPATS    (sizeof(patterns)/sizeof(patterns[0]))
  307.  
  308. static void
  309. drawcell(row, col, age)
  310.     unsigned char age;
  311. {
  312.     if (color)
  313.     XSetForeground(Dsp, Gc, (unsigned long) age);
  314.     if (pixels)
  315.     XFillRectangle(Dsp, Win, Gc,
  316.                xb + xs * col, yb + ys * row, xs, ys);
  317.     else
  318.     XPutImage(Dsp, Win, Gc, &logo,
  319.           0, 0, xb + xs * col, yb + ys * row,
  320.           lifeicon_width, lifeicon_height);
  321. }
  322.  
  323. static void
  324. erasecell(row, col)
  325. {
  326.     XFillRectangle(Dsp, Win, eraseGC,
  327.            xb + xs * col, yb + ys * row, xs, ys);
  328. }
  329.  
  330. static void
  331. spawn(loc)
  332.     unsigned char *loc;
  333. {
  334.     *(loc - NCOLS - 2 - 1) |= UPLT;
  335.     *(loc - NCOLS - 2) |= UP;
  336.     *(loc - NCOLS - 2 + 1) |= UPRT;
  337.     *(loc - 1) |= LT;
  338.     *(loc + 1) |= RT;
  339.     *(loc + NCOLS + 2 - 1) |= DNLT;
  340.     *(loc + NCOLS + 2) |= DN;
  341.     *(loc + NCOLS + 2 + 1) |= DNRT;
  342.     *(agebuf + (loc - buffer)) = 0;
  343. }
  344.  
  345. static void
  346. life_kill(loc)
  347.     unsigned char *loc;
  348. {
  349.     *(loc - NCOLS - 2 - 1) &= ~UPLT;
  350.     *(loc - NCOLS - 2) &= ~UP;
  351.     *(loc - NCOLS - 2 + 1) &= ~UPRT;
  352.     *(loc - 1) &= ~LT;
  353.     *(loc + 1) &= ~RT;
  354.     *(loc + NCOLS + 2 - 1) &= ~DNLT;
  355.     *(loc + NCOLS + 2) &= ~DN;
  356.     *(loc + NCOLS + 2 + 1) &= ~DNRT;
  357. }
  358.  
  359. static void
  360. setcell(row, col)
  361. {
  362.     register unsigned char *loc;
  363.  
  364.     loc = buffer + ((row + 1) * (NCOLS + 2)) + col + 1;
  365.     spawn(loc);
  366.     drawcell(row, col, 0);
  367. }
  368.  
  369. static long
  370. seconds()
  371. {
  372.     struct timeval foo;
  373.  
  374.     gettimeofday(&foo, (struct timezone *) 0);
  375.     return foo.tv_sec;
  376. }
  377.  
  378. void
  379. drawlife()
  380. {
  381.     unsigned char *loc,
  382.                *temploc;
  383.     int         row,
  384.                 col,
  385.                 cells = 0;
  386.     unsigned char fate;
  387.  
  388.  
  389.     loc = buffer + NCOLS + 2 + 1;
  390.     temploc = tempbuf;
  391.     /* copy the first 2 rows to the tempbuf */
  392.     bcopy(loc, temploc, NCOLS);
  393.     bcopy(loc + NCOLS + 2, temploc + NCOLS, NCOLS);
  394.     for (row = 0; row < NROWS; ++row) {
  395.     for (col = 0; col < NCOLS; ++col) {
  396.         fate = fates[*temploc];
  397.         *temploc = *(loc + (NCOLS + 2) * 2);
  398.         switch (fate) {
  399.         case BIRTH:
  400.         if (!(*(loc + 1) & RT)) {
  401.             spawn(loc);
  402.         }
  403.         /* NO BREAK */
  404.         case SAME:
  405.         if (*(loc + 1) & RT) {
  406.             register unsigned char *ageptr;
  407.             register unsigned char age;
  408.  
  409.             ++cells;
  410.             ageptr = agebuf + (loc - buffer);
  411.             age = *ageptr;
  412.             if (++age > 253)
  413.             age = 0;
  414.             *ageptr = age;
  415.             drawcell(row, col, age);
  416.         }
  417.         break;
  418.         case DEATH:
  419.         if (*(loc + 1) & RT) {
  420.             life_kill(loc);
  421.             erasecell(row, col);
  422.         }
  423.         break;
  424.         }
  425.         loc++;
  426.         temploc++;
  427.     }
  428.     loc += 2;
  429.     if (temploc >= tempbuf + NCOLS * 2)
  430.         temploc = tempbuf;
  431.     }
  432.     XFlush(Dsp);
  433.     usleep(delay * 1000);
  434.     if (!cells)
  435.     startTime = 0;
  436. }
  437.  
  438. static void
  439. init_fates()
  440. {
  441.     int         i,
  442.                 bits,
  443.                 neighbors;
  444.  
  445.     for (i = 0; i < 256; i++) {
  446.     neighbors = 0;
  447.     for (bits = i; bits; bits &= (bits - 1))
  448.         neighbors++;
  449.     if (neighbors == 3)
  450.         fates[i] = BIRTH;
  451.     else if (neighbors == 2)
  452.         fates[i] = SAME;
  453.     else
  454.         fates[i] = DEATH;
  455.     }
  456. }
  457.  
  458. void
  459. initlife(d, w, g, c, t, n)
  460.     Display    *d;
  461.     Window      w;
  462.     GC          g;
  463.     int         c,
  464.                 t,
  465.                 n;
  466. {
  467.     int         row,
  468.                 col;
  469.     int        *patptr;
  470.     XWindowAttributes xgwa;
  471.  
  472.     startTime = seconds();
  473.     shooter = 0;
  474.     Dsp = d;
  475.     Win = w;
  476.     Gc = g;
  477.     color = c;
  478.     timeout = t;
  479.     delay = n;
  480.  
  481.     if (eraseGC == (GC) 0) {
  482.     XGCValues   xgcv;
  483.  
  484.     xgcv.foreground = BlackPixel(Dsp, 0);
  485.     eraseGC = XCreateGC(Dsp, Win, GCForeground, &xgcv);
  486.  
  487.     srandom(time((long *) 0));
  488.     init_fates();
  489.     logo.data = lifeicon_bits;
  490.     logo.width = lifeicon_width;
  491.     logo.height = lifeicon_height;
  492.     logo.bytes_per_line = 4;
  493.     }
  494.     if (!color)
  495.     XSetForeground(Dsp, Gc, WhitePixel(Dsp, 0));
  496.  
  497.     XGetWindowAttributes(Dsp, Win, &xgwa);
  498.     width = xgwa.width;
  499.     height = xgwa.height;
  500.     xs = width / NCOLS;
  501.     ys = height / NROWS;
  502.     xb = (width - xs * NCOLS) / 2;
  503.     yb = (height - ys * NROWS) / 2;
  504.     pixels = (xs < lifeicon_width || ys < lifeicon_height);
  505.  
  506.     XFillRectangle(Dsp, Win, eraseGC, 0, 0, width, height);
  507.  
  508.     bzero(buffer, sizeof(buffer));
  509.     patptr = &patterns[(random() >> 3) % NPATS][0];
  510.     while ((col = *patptr++) != 99) {
  511.     row = *patptr++;
  512.     col += NCOLS / 2;
  513.     row += NROWS / 2;
  514.     setcell(row, col);
  515.     }
  516.     XFlush(Dsp);
  517.     sleep(1);
  518. }
  519.  
  520. int
  521. lifedone()
  522. {
  523.     int         elapsedTime = seconds() - startTime;
  524.  
  525.     if (elapsedTime > timeout)
  526.     return 1;
  527.     if (!shooter && elapsedTime > timeout / 2) {
  528.     setcell(0, 2);
  529.     setcell(1, 2);
  530.     setcell(2, 2);
  531.     setcell(2, 1);
  532.     setcell(1, 0);
  533.     shooter = 1;
  534.     }
  535.     return 0;
  536. }
  537.